package com.joysuch.wwyt.patrol.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.joysuch.wwyt.core.common.util.JsonUtil;
import com.joysuch.wwyt.core.common.util.SimpleDateFormatCache;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.monitoringcenter.service.LocateServerService;
import com.joysuch.wwyt.patrol.entity.PatrolSnapshotPath;
import com.joysuch.wwyt.patrol.entity.PatrolTask;
import com.joysuch.wwyt.patrol.entity.bean.*;
import com.joysuch.wwyt.patrol.mapper.PatrolSnapshotPathMapper;
import com.joysuch.wwyt.patrol.service.PatrolSnapshotPathService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.joysuch.wwyt.common.constant.Constant.SPLIT_COMMA;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author heqifeng
 * @since 2022-03-09
 */
@Service
@Slf4j
public class PatrolSnapshotPathServiceImpl extends ServiceImpl<PatrolSnapshotPathMapper, PatrolSnapshotPath> implements PatrolSnapshotPathService {

    @Autowired
    private LocateServerService locateServerService;
    @Autowired
    private BaseConfigService baseConfigService;
    @Autowired
    private BaseUserDao userDao;


    @Override
    public boolean saveSnapshotPath(PatrolTask task) {
        try{
            // url
            String url = buildUrl();
            // 参请求数
            SnapshotReqBean reqBean = buildParam(task);
            log.info("saveSnapshotPath task {} reqBean {}", task, reqBean);
            if (reqBean == null) {
                return false;
            }

            String loginToken = null;
            loginToken = locateServerService.getLoginToken();
            if (loginToken == null) {
                throw new RuntimeException("未获取到人员定位token");
            }

            // 请求
            ResponseEntity<SnapshotRespBean<LinkedHashMap>> response = locateServerService.rest(reqBean, loginToken, url, SnapshotRespBean.class);
            // 解析结果
            String pathJson = parseResp(response);

            log.info("saveSnapshotPath pathJson {}", pathJson);
            // 保存快照
            if (StringUtils.isNotBlank(pathJson)) {
                PatrolSnapshotPath snapshotPath = new PatrolSnapshotPath();
                snapshotPath.setUserId(task.getCheckUser())
                        .setTaskId(task.getId())
                        .setPathJson(pathJson);
                return save(snapshotPath);
            }
            return false;
        }catch (Exception e) {
            log.error("智能巡检-保存快照出错：",e);
        }
        return false;
    }

    @Override
    @Async
    public void saveSnapshotPath4Uncheck(List<UncheckSnapshotParam> snapshotParams) {
        String taskIdStr = snapshotParams.stream().map(UncheckSnapshotParam::getTaskId).map(String::valueOf).collect(Collectors.joining(SPLIT_COMMA));
        log.info(String.format("patrol task time out. save snapshot path. task ids:[%s]", taskIdStr));
        buildReqParamBatch(snapshotParams);
        // url
        String url = buildUrl();
        int saveCount = 0;
        for (UncheckSnapshotParam snapshotParam : snapshotParams) {
            SnapshotReqBean reqParam = snapshotParam.getReqParam();
            if (Objects.isNull(reqParam)) {
                continue;
            }
            // token有redis缓存，可循环获取
            String loginToken = locateServerService.getLoginToken(snapshotParam.getTenantId() ,snapshotParam.getOrgCode());
            if (StringUtils.isBlank(loginToken)) {
                log.info("未获取到人员定位token,tenantId: " + snapshotParam.getTenantId());
                continue;
            }
            ResponseEntity<SnapshotRespBean<LinkedHashMap>> response = locateServerService.rest(reqParam, loginToken, url, SnapshotRespBean.class);
            String pathJson = parseResp(response);
            // 保存快照
            if (StringUtils.isNotBlank(pathJson)) {
                PatrolSnapshotPath snapshotPath = new PatrolSnapshotPath();
                snapshotPath.setUserId(snapshotParam.getUserId())
                        .setTaskId(snapshotParam.getTaskId())
                        .setPathJson(pathJson);
                snapshotParam.setTenantId(snapshotParam.getTenantId());
                snapshotParam.setOrgCode(snapshotParam.getOrgCode());
                boolean saved = save(snapshotPath);
                if (saved) {
                    saveCount++;
                }
            }
        }
        log.info("save snapshot path end. count:" + saveCount);
    }

    @Override
    public PatrolSnapshotPath getPathByTaskId(Long taskId) {
        LambdaQueryWrapper<PatrolSnapshotPath> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PatrolSnapshotPath::getTaskId,taskId).last("limit 1");
        PatrolSnapshotPath snapshotPath = getOne(wrapper);
        return snapshotPath;
    }

    /**
     * 构造人员定位url
     * @return
     */
    private String buildUrl() {
        // 构造人员定位url
        BaseConfig ipConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_URL);
        // 获取人员定位系统协议（http/https）
        String httpIpPort = locateServerService.getHttpIpPort(ipConfig.getValue());
        // 拼接人员轨迹请求url
        return httpIpPort + "/api/v2/path/history";
    }

    /**
     * 构造请求参数
     * @param task
     * @return
     */
    private SnapshotReqBean buildParam(PatrolTask task) {
        if (task.getCheckStartTime() != null && task.getCheckEndTime() != null) {

            // 当前公司的buildId
            String buildId = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_CURRENT_BUILD_ID).getValue();
            SimpleDateFormat dateFormatter = SimpleDateFormatCache.getYmdhms();
            long hour = DateUtil.between(task.getCheckStartTime(), task.getCheckEndTime(), DateUnit.HOUR);
            // 如果任务持续时间大于24小时，则从任务完成时间向前截取24小时取快照
            String startTime = hour > 24 ? dateFormatter.format(DateUtil.offsetHour(task.getCheckEndTime(),-24)) : dateFormatter.format(task.getCheckStartTime());
            String endTime = dateFormatter.format(task.getCheckEndTime());
            BaseUser user = userDao.findById(task.getCheckUser()).get();
            String sn = user.getSn();
            if (StringUtils.isBlank(sn)) {
                return null;
            }
            return new SnapshotReqBean(buildId, startTime, endTime, sn);
        }
        return null;
    }


    private void buildReqParamBatch(List<UncheckSnapshotParam> snapshotParams) {
        // 人员id -> sn
        Set<Long> userIds = snapshotParams.stream().map(UncheckSnapshotParam::getUserId).collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(userIds)) {
            return;
        }
        List<BaseUser> users = userDao.getAllByIds(userIds);
        if (CollectionUtil.isEmpty(users)) {
            return;
        }
        Map<Long, String> userSnMap = users.stream().collect(Collectors.toMap(BaseUser::getId, BaseUser::getSn));

        // 建筑id
        String buildId = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_CURRENT_BUILD_ID).getValue();
        SimpleDateFormat dateFormatter = SimpleDateFormatCache.getYmdhms();
        // 构建请求参数
        for (UncheckSnapshotParam each : snapshotParams) {
            String sn = userSnMap.get(each.getUserId());
            if (StringUtils.isBlank(sn)) {
                continue;
            }
            SnapshotReqBean reqParam = new SnapshotReqBean();
            reqParam.setBuildId(buildId);
            reqParam.setSn(sn);
            long hour = DateUtil.between(each.getStartTime(), each.getEndTime(), DateUnit.HOUR);
            // 持续时间大于24小时，则从任务完成时间向前截取24小时取快照
            String startTime = hour > 24 ? dateFormatter.format(DateUtil.offsetHour(each.getEndTime(),-24)) : dateFormatter.format(each.getStartTime());
            String endTime = dateFormatter.format(each.getEndTime());
            reqParam.setStartTime(startTime);
            reqParam.setEndTime(endTime);
            each.setReqParam(reqParam);
        }

    }

    /**
     * 解析响应体
     * @param response
     * @return
     */
    private String parseResp(ResponseEntity<SnapshotRespBean<LinkedHashMap>> response) {
        SnapshotRespBean<LinkedHashMap> respBody = response.getBody();
        LinkedHashMap data = respBody.getData();
        // 点位数组
        if (data != null) {
            Object content = data.get("content");
            return JsonUtil.toJson(content);
        }
        return null;
    }

}
